package mysqlgo

import (
	"strings"
)

//Builder Model Builder
type Builder struct {
	model          interface{}
	modelInterface IModel
	dbAlias        string
	SQLBuilder
}

//Table 指定当前的数据表
func (builder *Builder) Table(tablename, alias string) *Builder {
	builder.table = Table{tablename, alias}
	return builder
}

//Where 指定查询条件
///For Example Where("id = ? and name = ?", 1, "admin")
func (builder *Builder) Where(condition string, args ...interface{}) *Builder {
	builder.SQLBuilder.Where(condition, args...)
	return builder
}

//Field 指定字段名称
func (builder *Builder) Field(field ...string) *Builder {
	builder.SQLBuilder.Field(field...)
	return builder
}

//Order 对查询的结果排序
///For Example (id desc, name asc) => map { 'id' : true, 'name' : false}
func (builder *Builder) Order(order map[string]bool) *Builder {
	builder.order = order
	return builder
}

//Group 一个或多个列对结果集进行分组
func (builder *Builder) Group(cols ...string) *Builder {
	builder.group = append(builder.group, cols...)
	return builder
}

//Limit 指定查询偏移量和记录数
func (builder *Builder) Limit(rowCount, offset uint) *Builder {
	builder.limit.Offset = offset
	builder.limit.RowCount = rowCount
	return builder
}

//Having 配合group方法完成从分组的结果中筛选
func (builder *Builder) Having(having string) *Builder {
	builder.having = having
	return builder
}

//Distinct 用于返回唯一不同的值
func (builder *Builder) Distinct(distinct bool) *Builder {
	builder.distinct = distinct
	return builder
}

//Join 用于根据两个或多个表中的列之间的关系，从这些表中查询数据
func (builder *Builder) Join(join Join) *Builder {
	builder.join = append(builder.join, join)
	return builder
}

//Union 用于合并两个或多个SELECT语句的结果集
func (builder *Builder) Union(selectSQL []string, all bool) *Builder {
	builder.union.SelectSQL = selectSQL
	builder.union.All = all
	return builder
}

//LastSQL 最后执行生成的SQL语句
func (builder *Builder) LastSQL() string {
	return builder.lastSQL
}

//Find 查找单向数据
func (builder *Builder) Find(dest interface{}) error {
	sql := builder.SQLBuilder.BuildSQL(query, nil)
	if sql == "" {
		return GetError(SQLNull)
	}
	db := DB(builder.dbAlias).Unsafe()
	if db == nil {
		return GetError(DBNull)
	}
	return db.Get(&dest, sql, builder.whereArgs...)
}

//Select 查询多条数据
func (builder *Builder) Select(dest interface{}) error {
	sql := builder.SQLBuilder.BuildSQL(query, nil)
	if sql == "" {
		return GetError(SQLNull)
	}
	db := DB(builder.dbAlias).Unsafe()
	if db == nil {
		return GetError(DBNull)
	}
	return db.Select(dest, sql, builder.whereArgs...)
}

//Add 新增数据
func (builder *Builder) Add(data interface{}) (int64, error) {
	fields := &field{}
	fields.parseData(data)
	if len(fields.names) == 0 {
		return -1, GetError(KeyNull)
	}
	builder.field = strings.Join(fields.names, ",")
	sql := builder.SQLBuilder.BuildSQL(insert, nil)
	if sql == "" {
		return -1, GetError(SQLNull)
	}
	db := DB(builder.dbAlias).Unsafe()
	if db == nil {
		return -1, GetError(DBNull)
	}
	result, err := db.Exec(sql, fields.values...)
	if err != nil {
		return -1, err
	}
	return result.LastInsertId()
}

//AddAll 新增多条数据
func (builder *Builder) AddAll(datas ...interface{}) error {

	fields := &field{}
	values, err := fields.parseDatas(datas...)
	if err != nil {
		return err
	}

	if len(fields.names) == 0 {
		return GetError(KeyNull)
	}
	builder.field = strings.Join(fields.names, ",")

	sql := builder.SQLBuilder.BuildSQL(insert, nil)

	if sql == "" {
		return GetError(SQLNull)
	}

	db := DB(builder.dbAlias).Unsafe()
	if db == nil {
		return GetError(DBNull)
	}

	tx := db.MustBegin()
	for _, value := range values {
		result := tx.MustExec(sql, value...)
		_, err := result.LastInsertId()
		if err != nil {
			tx.Rollback()
			return err
		}
	}
	return tx.Commit()
}

//Update 更新数据
func (builder *Builder) Update(data map[string]interface{}) (int64, error) {
	if builder.where == "" {
		return -1, GetError(WhereNull)
	}
	sql := builder.SQLBuilder.BuildSQL(update, data)
	if sql == "" {
		return -1, GetError(SQLNull)
	}
	db := DB(builder.dbAlias).Unsafe()
	if db == nil {
		return -1, GetError(DBNull)
	}

	result, err := db.Exec(sql, builder.args...)
	if err != nil {
		return -1, err
	}
	return result.RowsAffected()
}

//Delete 删除数据
func (builder *Builder) Delete() (int64, error) {
	if builder.where == "" {
		return -1, GetError(WhereNull)
	}

	sql := builder.SQLBuilder.BuildSQL(delete, nil)
	if sql == "" {
		return -1, GetError(SQLNull)
	}

	db := DB(builder.dbAlias).Unsafe()
	if db == nil {
		return -1, GetError(DBNull)
	}

	result, err := db.Exec(sql, builder.whereArgs...)
	if err != nil {
		return -1, err
	}

	return result.RowsAffected()

}
